package main

import (
	"database/sql"
	"errors"
	"fmt"
	pb "ihos/ihos"
	"log"
	"time"

	tm "github.com/golang/protobuf/ptypes/timestamp"
)

type guahao struct {
	id              int32
	pbbm            string //排班编码
	hybm            string //号源唯一编码
	sdls            string //锁定流水ID
	sdqq            string //锁定请求号
	sfqq            string //释放请求号
	ghls            string //挂号流水ID
	ghqq            string //挂号请求号
	thqq            string //退号请求号
	orderid         string //挂号的时候返回流水ID
	identifyno      string //看病人身份证号码
	telephone       string //联系电话
	patientname     string //病人姓名
	patientsex      int32  //病人性别
	patientaddress  string //病人住址
	cliniccard      string //就诊卡号
	doctorname      string //医生姓名
	doctorcode      string //医生代码
	deptname        string //科室名称
	deptcode        string //科室代码
	price           int32  //出诊费
	clinicprice     int32  //诊疗费
	visitprice      int32  //挂号费
	otherprice      int32  //其他诊疗费用
	timename        string //时间名称，上午班/下午班/全天班
	timecode        int32  //时间代码 上午1 下午2 晚上3
	status          int32  //挂号状态
	statusname      string //状态名称
	ispayfee        bool   //是否支付
	remark          string //备注
	operatorname    string //操作人名称
	operatorid      string //操作人ID
	jzrq            int64  //实际就诊时间
	patientid       string //病人ID
	visitdate       int64  //计划就诊日期
	payeridentifyno string //挂号人身份证号码
	hoscode         string //医院编码
	hosname         string //医院名称
	remain          int32  //前面还有几个在线且未叫号
	createtime      int64  //挂号建立时间
	guahaotype      int32  //挂号类型
}

func (w *guahao) GetFromDB(id int32) error {
	sql := "SELECT id,pbbm,hybm,sdls,sdqq,sfqq,ghls,ghqq,thqq,orderid,identifyno,telephone,patientname,patientsex,patientaddress,cliniccard,doctorname,doctorcode,deptname,deptcode,price,clinicprice,visitprice,otherprice,timename,timecode,status,statusname,ispayfee,remark,operatorname,operatorid,jzrq,patientid,visitdate,payeridentifyno,hoscode,hosname,createtime,type FROM guahao WHERE id=$1"
	return DBConn.db.QueryRow(sql, id).Scan(&w.id, &w.pbbm, &w.hybm, &w.sdls, &w.sdqq, &w.sfqq, &w.ghls, &w.ghqq, &w.thqq, &w.orderid, &w.identifyno, &w.telephone, &w.patientname, &w.patientsex, &w.patientaddress, &w.cliniccard, &w.doctorname, &w.doctorcode, &w.deptname, &w.deptcode, &w.price, &w.clinicprice, &w.visitprice, &w.otherprice, &w.timename, &w.timecode, &w.status, &w.statusname, &w.ispayfee, &w.remark, &w.operatorname, &w.operatorid, &w.jzrq, &w.patientid, &w.visitdate, &w.payeridentifyno, &w.hoscode, &w.hosname, &w.createtime, &w.guahaotype)
}

func (w *guahao) GetFromDBByOrderId() error {
	sql := "SELECT id,pbbm,hybm,sdls,sdqq,sfqq,ghls,ghqq,thqq,orderid,identifyno,telephone,patientname,patientsex,patientaddress,cliniccard,doctorname,doctorcode,deptname,deptcode,price,clinicprice,visitprice,otherprice,timename,timecode,status,statusname,ispayfee,remark,operatorname,operatorid,jzrq,patientid,visitdate,payeridentifyno,hoscode,hosname,createtime,type FROM guahao WHERE orderid=$1"
	return DBConn.db.QueryRow(sql, w.orderid).Scan(&w.id, &w.pbbm, &w.hybm, &w.sdls, &w.sdqq, &w.sfqq, &w.ghls, &w.ghqq, &w.thqq, &w.orderid, &w.identifyno, &w.telephone, &w.patientname, &w.patientsex, &w.patientaddress, &w.cliniccard, &w.doctorname, &w.doctorcode, &w.deptname, &w.deptcode, &w.price, &w.clinicprice, &w.visitprice, &w.otherprice, &w.timename, &w.timecode, &w.status, &w.statusname, &w.ispayfee, &w.remark, &w.operatorname, &w.operatorid, &w.jzrq, &w.patientid, &w.visitdate, &w.payeridentifyno, &w.hoscode, &w.hosname, &w.createtime, &w.guahaotype)
}

// GuaHao是否有效，可以候诊
func (w *guahao) IsValid() bool {
	// 挂号状态结束，但是jzri为0，不应该出现这种状态，出现了视作无效
	if w.status == 0 && w.jzrq == 0 {
		return false
	}

	//状态不对
	if w.status == 2 || w.status == 5 {
		// log.Println("IsValid:0 false")
		return false
	}

	//取当前时间
	tn := time.Now().Unix()
	t0 := GetNowHx(0)
	t12 := GetNowHx(12)
	t18 := GetNowHx(18)
	t24 := GetNowHx(24)
	// log.Println(tn, t0, t12, t18, t24, w.visitdate)
	//就诊时间已经过了一天
	if w.jzrq != 0 && (w.jzrq < t0 || w.jzrq >= t24) {
		// log.Println("IsValid:1 false", w.jzrq)
		return false
	}
	//随到随诊，visitdate已经到了
	if w.timecode == 4 && w.visitdate < t24 {
		// log.Println("IsValid:2 true")
		return true
	}
	//指定visitdate
	if time.Unix(w.visitdate, 0).Day() == time.Unix(t0, 0).Day() {
		if w.timecode == 0 {
			// log.Println("IsValid:3 true")
			return true
		}
		if w.timecode == 1 && tn <= t12 {
			// log.Println("IsValid:4 true")
			return true
		}
		if w.timecode == 2 && tn > t12 && tn <= t18 {
			// log.Println("IsValid:5 true")
			return true
		}
		if w.timecode == 3 && tn > t18 && tn < t24 {
			// log.Println("IsValid:6 true")
			return true
		}
	}
	// log.Println("IsValid:7 false")
	return false
}

func (w *guahao) GetGuaHaoList() (ghs []*guahao, err error) {
	// log.Println("GetGuaHaoList:", w)
	var rows *sql.Rows
	out := make([]*guahao, 0)
	sqlStr := ""
	if w.id > 0 {
		sqlStr = "SELECT id,pbbm,hybm,sdls,sdqq,sfqq,ghls,ghqq,thqq,orderid,identifyno,telephone,patientname,patientsex,patientaddress,cliniccard,doctorname,doctorcode,deptname,deptcode,price,clinicprice,visitprice,otherprice,timename,timecode,status,statusname,ispayfee,remark,operatorname,operatorid,jzrq,patientid,visitdate,payeridentifyno,hoscode,hosname,createtime,type FROM guahao WHERE id=" + fmt.Sprint(w.id)
	} else {
		sqlStr = "SELECT id,pbbm,hybm,sdls,sdqq,sfqq,ghls,ghqq,thqq,orderid,identifyno,telephone,patientname,patientsex,patientaddress,cliniccard,doctorname,doctorcode,deptname,deptcode,price,clinicprice,visitprice,otherprice,timename,timecode,status,statusname,ispayfee,remark,operatorname,operatorid,jzrq,patientid,visitdate,payeridentifyno,hoscode,hosname,createtime,type FROM guahao"
		cond := make([]string, 0)
		if len(w.pbbm) > 0 {
			cond = append(cond, "pbbm='"+w.pbbm+"'")
		}
		if len(w.orderid) > 0 {
			cond = append(cond, "orderid='"+w.orderid+"'")
		}
		if len(w.identifyno) > 0 {
			cond = append(cond, "identifyno='"+w.identifyno+"'")
		}
		if len(w.payeridentifyno) > 0 {
			cond = append(cond, "payeridentifyno='"+w.payeridentifyno+"'")
		}
		if len(w.deptcode) > 0 {
			cond = append(cond, "deptcode='"+w.deptcode+"'")
		}
		if len(w.doctorcode) > 0 {
			cond = append(cond, "(doctorcode='"+w.doctorcode+"' OR doctorcode='')")
		}
		if w.visitdate > 0 {
			cond = append(cond, "visitdate>="+fmt.Sprint(w.visitdate))
		}
		if len(w.hoscode) > 0 {
			cond = append(cond, "hoscode='"+w.hoscode+"'")
		}
		if len(cond) > 0 {
			sqlStr += " WHERE "
			sep := ""
			for _, v := range cond {
				sqlStr += sep + v
				sep = " AND "
			}
		} else {
			return nil, errors.New("Miss Param")
		}
		sqlStr += " ORDER BY id DESC LIMIT 500"
	}
	// log.Println("SQL:", sqlStr)
	rows, err = DBConn.db.Query(sqlStr)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	defer rows.Close()
	for rows.Next() {
		w := &guahao{}
		if err = rows.Scan(&w.id, &w.pbbm, &w.hybm, &w.sdls, &w.sdqq, &w.sfqq, &w.ghls, &w.ghqq, &w.thqq, &w.orderid, &w.identifyno, &w.telephone, &w.patientname, &w.patientsex, &w.patientaddress, &w.cliniccard, &w.doctorname, &w.doctorcode, &w.deptname, &w.deptcode, &w.price, &w.clinicprice, &w.visitprice, &w.otherprice, &w.timename, &w.timecode, &w.status, &w.statusname, &w.ispayfee, &w.remark, &w.operatorname, &w.operatorid, &w.jzrq, &w.patientid, &w.visitdate, &w.payeridentifyno, &w.hoscode, &w.hosname, &w.createtime, &w.guahaotype); err != nil {
			log.Println(err)
			//return nil, err
		} else {
			out = append(out, w)
		}
	}
	return out, nil
}

func (w *guahao) GetGuaHaoDuiZhangList() (ghs []*guahao, err error) {
	// log.Println("GetGuaHaoDuiZhangList:", w)
	var rows *sql.Rows
	out := make([]*guahao, 0)
	sqlStr := "SELECT id,pbbm,hybm,sdls,sdqq,sfqq,ghls,ghqq,thqq,orderid,identifyno,telephone,patientname,patientsex,patientaddress,cliniccard,doctorname,doctorcode,deptname,deptcode,price,clinicprice,visitprice,otherprice,timename,timecode,status,statusname,ispayfee,remark,operatorname,operatorid,jzrq,patientid,visitdate,payeridentifyno,hoscode,hosname,createtime,type FROM guahao"
	cond := make([]string, 0)
	if w.visitdate > 0 {
		cond = append(cond, "visitdate>="+fmt.Sprint(w.visitdate))
		cond = append(cond, "visitdate<"+fmt.Sprint(w.visitdate+24*3600))
	}
	if w.createtime > 0 {
		cond = append(cond, "createtime>="+fmt.Sprint(w.createtime))
		cond = append(cond, "createtime<"+fmt.Sprint(w.createtime+24*3600))
	}
	if w.guahaotype > 0 {
		if w.guahaotype == 4 {
			cond = append(cond, "(type=5 OR type=6 OR type=7)")
		} else {
			cond = append(cond, "type="+fmt.Sprint(w.guahaotype))
		}
	}
	if len(w.hoscode) > 0 {
		cond = append(cond, "hoscode='"+w.hoscode+"'")
	}
	if len(cond) > 0 {
		sqlStr += " WHERE "
		sep := ""
		for _, v := range cond {
			sqlStr += sep + v
			sep = " AND "
		}
	}
	sqlStr += " ORDER BY id DESC LIMIT 500"
	// log.Println("SQL:", sqlStr)
	rows, err = DBConn.db.Query(sqlStr)
	if err != nil {
		log.Println(err)
		return nil, err
	}
	defer rows.Close()
	for rows.Next() {
		w := &guahao{}
		if err = rows.Scan(&w.id, &w.pbbm, &w.hybm, &w.sdls, &w.sdqq, &w.sfqq, &w.ghls, &w.ghqq, &w.thqq, &w.orderid, &w.identifyno, &w.telephone, &w.patientname, &w.patientsex, &w.patientaddress, &w.cliniccard, &w.doctorname, &w.doctorcode, &w.deptname, &w.deptcode, &w.price, &w.clinicprice, &w.visitprice, &w.otherprice, &w.timename, &w.timecode, &w.status, &w.statusname, &w.ispayfee, &w.remark, &w.operatorname, &w.operatorid, &w.jzrq, &w.patientid, &w.visitdate, &w.payeridentifyno, &w.hoscode, &w.hosname, &w.createtime, &w.guahaotype); err != nil {
			log.Println(err)
			//return nil, err
		} else {
			out = append(out, w)
		}
	}
	return out, nil
}

func (w *guahao) SaveToDB(id int32) error {
	log.Println("SaveToDB")
	sql := ""
	var err error
	if id > 0 { //update
		sql = "UPDATE guahao set pbbm=$1,hybm=$2,sdls=$3,sdqq=$4,sfqq=$5,ghls=$6,ghqq=$7,thqq=$8,orderid=$9,identifyno=$10,telephone=$11,patientname=$12,patientsex=$13,patientaddress=$14,cliniccard=$15,doctorname=$16,doctorcode=$17,deptname=$18,deptcode=$19,price=$20,clinicprice=$21,visitprice=$22,otherprice=$23,timename=$24,timecode=$25,status=$26,statusname=$27,ispayfee=$28,remark=$29,operatorname=$30,operatorid=$31,jzrq=$32,patientid=$33,visitdate=$34,payeridentifyno=$35,hoscode=$36,hosname=$37,createtime=$38,type=$39 where id=$40 RETURNING id"
		err = DBConn.db.QueryRow(sql, w.pbbm, w.hybm, w.sdls, w.sdqq, w.sfqq, w.ghls, w.ghqq, w.thqq, w.orderid, w.identifyno, w.telephone, w.patientname, w.patientsex, w.patientaddress, w.cliniccard, w.doctorname, w.doctorcode, w.deptname, w.deptcode, w.price, w.clinicprice, w.visitprice, w.otherprice, w.timename, w.timecode, w.status, w.statusname, w.ispayfee, w.remark, w.operatorname, w.operatorid, w.jzrq, w.patientid, w.visitdate, w.payeridentifyno, w.hoscode, w.hosname, w.createtime, w.guahaotype, w.id).Scan(&w.id)
	} else { //insert
		sql = "INSERT INTO guahao(pbbm,hybm,sdls,sdqq,sfqq,ghls,ghqq,thqq,orderid,identifyno,telephone,patientname,patientsex,patientaddress,cliniccard,doctorname,doctorcode,deptname,deptcode,price,clinicprice,visitprice,otherprice,timename,timecode,status,statusname,ispayfee,remark,operatorname,operatorid,jzrq,patientid,visitdate,payeridentifyno,hoscode,hosname,createtime,type) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33,$34,$35,$36,$37,$38,$39) RETURNING id"
		err = DBConn.db.QueryRow(sql, w.pbbm, w.hybm, w.sdls, w.sdqq, w.sfqq, w.ghls, w.ghqq, w.thqq, w.orderid, w.identifyno, w.telephone, w.patientname, w.patientsex, w.patientaddress, w.cliniccard, w.doctorname, w.doctorcode, w.deptname, w.deptcode, w.price, w.clinicprice, w.visitprice, w.otherprice, w.timename, w.timecode, w.status, w.statusname, w.ispayfee, w.remark, w.operatorname, w.operatorid, w.jzrq, w.patientid, w.visitdate, w.payeridentifyno, w.hoscode, w.hosname, w.createtime, w.guahaotype).Scan(&w.id)
	}
	log.Println(sql)
	return err
}

func (w *guahao) UpdateStatus() error {
	sql := ""
	var err error
	if w.id > 0 { //update
		sql = "UPDATE guahao set status=$1,statusname=$2 where id=$3 RETURNING id"
		err = DBConn.db.QueryRow(sql, w.status, w.statusname, w.id).Scan(&w.id)
	}
	return err
}

func (w *guahao) SaveToDBByOrderid() error {
	sql := ""
	var err error
	if len(w.orderid) > 0 { //update
		sql = "UPDATE guahao set pbbm=$1,hybm=$2,sdls=$3,sdqq=$4,sfqq=$5,ghls=$6,ghqq=$7,thqq=$8,orderid=$9,identifyno=$10,telephone=$11,patientname=$12,patientsex=$13,patientaddress=$14,cliniccard=$15,doctorname=$16,doctorcode=$17,deptname=$18,deptcode=$19,price=$20,clinicprice=$21,visitprice=$22,otherprice=$23,timename=$24,timecode=$25,status=$26,statusname=$27,ispayfee=$28,remark=$29,operatorname=$30,operatorid=$31,jzrq=$32,patientid=$33,visitdate=$34,payeridentifyno=$35,hoscode=$36,hosname=$37,createtime=$38,type=$39 where orderid=$40 RETURNING id"
		err = DBConn.db.QueryRow(sql, w.pbbm, w.hybm, w.sdls, w.sdqq, w.sfqq, w.ghls, w.ghqq, w.thqq, w.orderid, w.identifyno, w.telephone, w.patientname, w.patientsex, w.patientaddress, w.cliniccard, w.doctorname, w.doctorcode, w.deptname, w.deptcode, w.price, w.clinicprice, w.visitprice, w.otherprice, w.timename, w.timecode, w.status, w.statusname, w.ispayfee, w.remark, w.operatorname, w.operatorid, w.jzrq, w.patientid, w.visitdate, w.payeridentifyno, w.hoscode, w.hosname, w.createtime, w.guahaotype, w.orderid).Scan(&w.id)
	}
	return err
}

func (w *guahao) toPB() *pb.GuaHao {
	d := &pb.GuaHao{
		ID:             w.id,
		PBBM:           w.pbbm,
		HYBM:           w.hybm,
		SDLS:           w.sdls,
		SDQQ:           w.sdqq,
		SFQQ:           w.sfqq,
		GHLS:           w.ghls,
		GHQQ:           w.ghqq,
		THQQ:           w.thqq,
		ORDERID:        w.orderid,
		IDENTIFYNO:     w.identifyno,
		TELEPHONE:      w.telephone,
		PATIENTNAME:    w.patientname,
		PATIENTSEX:     pb.GENDER(w.patientsex),
		PATIENTADDRESS: w.patientaddress,
		CLINICCARD:     w.cliniccard,
		DOCTORNAME:     w.doctorname,
		DOCTORCODE:     w.doctorcode,
		DEPTNAME:       w.deptname,
		DEPTCODE:       w.deptcode,
		PRICE:          w.price,
		CLINICPRICE:    w.clinicprice,
		VISITPRICE:     w.visitprice,
		OTHERPRICE:     w.otherprice,
		TIMENAME:       w.timename,
		TIMECODE:       pb.TIMECODE1(w.timecode),
		STATUS:         pb.GuaHao_GuaHaoZhuangTai(w.status),
		STATUSNAME:     w.statusname,
		ISPAYFEE:       w.ispayfee,
		REMARK:         w.remark,
		OPERATORNAME:   w.operatorname,
		OPERATORID:     w.operatorid,
		VISITDATE:      &tm.Timestamp{Seconds: w.visitdate},
		PATIENTID:      w.patientid,
		JZRQ:           &tm.Timestamp{Seconds: w.jzrq},
		ISVALID:        w.IsValid(),
		PAYER:          w.payeridentifyno,
		ZT:             pb.GuaHao_HOUZHEN_NOTENTER,
		HOSCODE:        w.hoscode,
		HOSNAME:        w.hosname,
		REMAIN:         w.remain,
		CREATE_TIME:    &tm.Timestamp{Seconds: w.createtime},
		TYPE:           pb.GuaHao_GUAHAO_TYPE(w.guahaotype),
	}
	// if d.GetISVALID() == true
	if true {
		d.REMAIN, d.PAIDUIORDER, d.PAIDUINUM = menZhenPaiDui.GetRemainByHuaHao(w.id)
	}
	return d
}

func (w *guahao) fromPB(p *pb.GuaHao) *guahao {
	w.id = p.GetID()
	w.pbbm = p.GetPBBM()
	w.hybm = p.GetHYBM()
	w.sdls = p.GetSDLS()
	w.sdqq = p.GetSDQQ()
	w.sfqq = p.GetSFQQ()
	w.ghls = p.GetGHLS()
	w.ghqq = p.GetGHQQ()
	w.thqq = p.GetTHQQ()
	w.orderid = p.GetORDERID()
	w.identifyno = p.GetIDENTIFYNO()
	w.telephone = p.GetTELEPHONE()
	w.patientname = p.GetPATIENTNAME()
	w.patientsex = int32(p.GetPATIENTSEX())
	w.patientaddress = p.GetPATIENTADDRESS()
	w.cliniccard = p.GetCLINICCARD()
	w.doctorname = p.GetDOCTORNAME()
	w.doctorcode = p.GetDOCTORCODE()
	w.deptname = p.GetDEPTNAME()
	w.deptcode = p.GetDEPTCODE()
	w.price = p.GetPRICE()
	w.clinicprice = p.GetCLINICPRICE()
	w.visitprice = p.GetVISITPRICE()
	w.otherprice = p.GetOTHERPRICE()
	w.timename = p.GetTIMENAME()
	w.timecode = int32(p.GetTIMECODE())
	w.status = int32(p.GetSTATUS())
	w.statusname = p.GetSTATUSNAME()
	w.ispayfee = p.GetISPAYFEE()
	w.remark = p.GetREMARK()
	w.operatorname = p.GetOPERATORNAME()
	w.operatorid = p.GetOPERATORID()
	w.jzrq = p.GetJZRQ().GetSeconds()
	w.patientid = p.GetPATIENTID()
	w.visitdate = p.GetVISITDATE().GetSeconds()
	w.payeridentifyno = p.GetPAYER()
	w.hoscode = p.GetHOSCODE()
	w.hosname = p.GetHOSNAME()
	w.createtime = p.GetCREATE_TIME().GetSeconds()
	w.guahaotype = int32(p.GetTYPE())
	return w
}
